﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace VTESCore.Utilities
{

	public static class CardReaderUtils
	{
		/// <summary>
		/// Reads in the following values:
		/// Name,Type,Clan,Adv,Group,Capacity,Disciplines,Card Text,Set,Title,Banned,Artist
		/// and uses them to populate a CryptCard object. It also returns a string List of these values
		/// </summary>
		/// <param name="crypt_card_line">Raw line containing the crypt card values as read by the csv file</param>
		/// <param name="crypt_card">Crypt Card object to fill with the read data</param>
		/// <returns>List of the crypt card values read as strings</returns>
		public static string[] ReadCryptCardValues( StreamReader sr, List<VTESCard> crypt_cards )
		{
			string[] useful_values = new string[12];
			ReadVTESCardValues( sr, useful_values, 12 );

			// now let's populate the CryptCard object, remember the values we have now in the array are the following:
			// 0:Name,1:Type,2:Clan,3:Adv,4:Group,5:Capacity,6:Disciplines,7:Card Text,8:Set,9:Title,10:Banned,11:Artist

			foreach ( ReleaseSet release_set in GenerateVTESCardsFromReleaseSets( useful_values[ 8 ] ) )
			{
				CryptCard crypt_card = new CryptCard();

				crypt_card.Name = useful_values[ 0 ];
				crypt_card.CardType = VampireEnumUtils.GetCardType( useful_values[ 1 ] );
				crypt_card.Clan = VampireEnumUtils.GetClan( useful_values[ 2 ] );
				crypt_card.Advanced = useful_values[ 3 ] == "Advanced";

				int group;
				crypt_card.Group = int.TryParse( useful_values[ 4 ], out group ) ? group : 0;

				int blood_capacity;
				crypt_card.BloodCapacity = int.TryParse( useful_values[ 5 ], out blood_capacity ) ? blood_capacity : 0;

				PopulateCryptCardDisciplines( useful_values[ 6 ], crypt_card );
				crypt_card.CardText = useful_values[ 7 ];
				crypt_card.Title = VampireEnumUtils.GetTitle( useful_values[ 9 ] );
				crypt_card.Banned = useful_values[ 10 ] == "Banned"; // might be something else too, no idea cause nothing seems to be banned.
				crypt_card.Artist = useful_values[ 11 ];

				crypt_card.Set = release_set;

				crypt_cards.Add( crypt_card );
			}

			return useful_values;
		}

		private static void PopulateCryptCardDisciplines( string disciplines_string, CryptCard crypt_card )
		{
			char[] delimiter = { ' ' };
			string[] disciplines = disciplines_string.Split( delimiter, StringSplitOptions.RemoveEmptyEntries );
			for ( int i = 0; i < disciplines.GetLength( 0 ); i++ )
			{
				crypt_card.Disciplines.Add( VampireEnumUtils.GetDiscipline( disciplines[i] ) );
			}
		}

		private static List<ReleaseSet> GenerateVTESCardsFromReleaseSets( string sets_string )
		{
			List<ReleaseSet> sets = new List<ReleaseSet>();
			string[] delimiter = { ",", ", ", " " };
			string[] sets_strings = sets_string.Split( delimiter, StringSplitOptions.RemoveEmptyEntries );
			for ( int i = 0; i < sets_strings.GetLength( 0 ); i++ )
			{
				string release_set = sets_strings[ i ];
				// now just keep the part before the ":" or "-". This is the main set name without the clarification
				string[] more_delimiters = { ":", "-" };
				release_set = release_set.Split( more_delimiters, StringSplitOptions.RemoveEmptyEntries )[0];
				sets.Add( VampireEnumUtils.GetReleaseSet(release_set) );
			}
			return sets;
		}

		public static string[] ReadLibraryCardValues( StreamReader sr, List<VTESCard> library_cards )
		{
			// now let's populate the LibraryCard object, remember the values we have now in the array are the following:
			// 0:Name 1:Type 2:Clan 3:Discipline 4:Pool Cost 5:Blood Cost 6:Conviction Cost,
			// 6:Burn Option 7:Card Text 8:Flavor Text 9:Set 10:Requirement 11:Banned 12:Artist
			string[] useful_values = new string[14];

			ReadVTESCardValues( sr, useful_values, 14 );

			foreach ( ReleaseSet release_set in GenerateVTESCardsFromReleaseSets(useful_values[10]) )
			{
				LibraryCard library_card = new LibraryCard();

				library_card.Name = useful_values[ 0 ];

				string[] delimeters = { "/", " / ", " & " };
				string[] card_types = useful_values[ 1 ].Split( delimeters, StringSplitOptions.RemoveEmptyEntries );
				for ( int i = 0; i < card_types.GetLength( 0 ); i++ )
				{
					library_card.CardTypes.Add( VampireEnumUtils.GetCardType( card_types[ i ] ) );
				}

				string[] clan_requirements = useful_values[ 2 ].Split( delimeters, StringSplitOptions.RemoveEmptyEntries );
				for ( int i = 0; i < clan_requirements.GetLength( 0 ); i++ )
				{
					library_card.ClanRequirements.Add( VampireEnumUtils.GetClan( clan_requirements[ i ] ) );
				}

				string[] discipline_requirements = useful_values[ 3 ].Split( delimeters, StringSplitOptions.RemoveEmptyEntries );
				for ( int i = 0; i < discipline_requirements.GetLength( 0 ); i++ )
				{
					library_card.DisciplineRequirements.Add( VampireEnumUtils.GetDiscipline( discipline_requirements[ i ] ) );
				}

				int pool_cost;
				library_card.PoolCost = int.TryParse( useful_values[ 4 ], out pool_cost ) ? pool_cost : 0;

				int blood_cost;
				library_card.BloodCost = int.TryParse( useful_values[ 5 ], out blood_cost ) ? blood_cost : 0;

				int conviction_cost;
				library_card.ConvictionCost = int.TryParse( useful_values[ 6 ], out conviction_cost ) ? conviction_cost : 0;

				library_card.BurnOption = useful_values[ 7 ] == "Y";

				library_card.CardText = useful_values[ 8 ];

				library_card.FlavourText = useful_values[ 9 ];

				library_card.OtherRequirements = useful_values[ 11 ];

				library_card.Banned = useful_values[ 12 ] == "Banned"; // might be something else too, no idea cause nothing seems to be banned.

				library_card.Artist = useful_values[ 13 ];

				library_card.Set = release_set;

				library_cards.Add( library_card );
			}

			return useful_values;
		}

		private static void ReadVTESCardValues( StreamReader sr, string[] useful_values, int num_values )
		{
			int current_value_index = 0;
			while ( current_value_index < num_values )
			{
				bool finished_reading_value = false;
				string value = "";
				while ( !finished_reading_value )
				{
					char next_char = (char)sr.Read();

					if ( next_char != '"' )
					{
						value += next_char;
						continue;
					}

					if ( next_char == '"' )
					{
						value += next_char;
						next_char = (char)sr.Read();
						if ( next_char != '"' )
						{
							value = value.Remove( value.Length - 1 );	// remove the quotes
							useful_values[current_value_index] = value;
							finished_reading_value = true;

							// finally move the cursor to the beginning of the next value
							next_char = (char)sr.Read();
							while ( next_char != '"' && !sr.EndOfStream )
							{
								next_char = (char)sr.Read();
							}
							continue;
						}
						else
						{
							while ( sr.Peek() != '"' )
							{
								next_char = (char)sr.Read();
								value += next_char;
							}
						}
					}
				}
				current_value_index++;
			}
		}
	}
}
